package fr.afcepf.atod16.groupe1.projet2.serviceCommande;

import fr.afcepf.atod16.groupe1.projet2.dao.DaoCommandeStock;
import fr.afcepf.atod16.groupe1.projet2.dao.DaoProduitStock;
import fr.afcepf.atod16.groupe1.projet2.dto.DtoCommande;
import fr.afcepf.atod16.groupe1.projet2.dto.DtoCommandeStock;
import fr.afcepf.atod16.groupe1.projet2.dto.DtoLigneCommande;
import fr.afcepf.atod16.groupe1.projet2.dto.DtoLigneCommandeStock;
import fr.afcepf.atod16.groupe1.projet2.dto.DtoProduitStock;
import fr.afcepf.atod16.groupe1.projet2.enumerations.EtatLivraison;
import fr.afcepf.atod16.groupe1.projet2.exception.ActivationException;
import fr.afcepf.atod16.groupe1.projet2.exception.EtatLivraisonException;
import fr.afcepf.atod16.groupe1.projet2.exception.InvalidArgumentException;
import fr.afcepf.atod16.groupe1.projet2.exception.NotExistException;
import fr.afcepf.atod16.groupe1.projet2.exception.StockException;
import fr.afcepf.groupe1.projet1.servicemaj.DtoMajCommande;
import fr.afcepf.groupe1.projet1.servicemaj.EtatLivraisonException_Exception;
import fr.afcepf.groupe1.projet1.servicemaj.InvalidArgumentException_Exception;
import fr.afcepf.groupe1.projet1.servicemaj.NotExistException_Exception;
import fr.afcepf.groupe1.projet1.servicemaj.ServiceMaj;
import fr.afcepf.groupe1.projet1.servicemaj.ServiceMajWebservice;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.jws.WebService;

/**
 * Service métier de gestion des commandes
 * @author cedric
 */
@Stateless
@WebService(endpointInterface="fr.afcepf.atod16.groupe1.projet2.serviceCommande.ServiceCommandeStockWebservice", serviceName="ServiceCommande")
public class ServiceCommandeStock implements ServiceCommandeStockLocal, ServiceCommandeStockWebservice {
    
    @EJB
    private DaoCommandeStock daoCommande;
    
    @EJB
    private DaoProduitStock daoProduit;

    public ServiceCommandeStock() {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<DtoCommandeStock> getListe() {
        return daoCommande.lister();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public DtoCommandeStock getDetail(Integer id) {
        return daoCommande.rechercherParId(id);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void modifierEtatLivraison(Integer id, EtatLivraison etatLivraison) {
        
        // update en base de donnée
        DtoCommandeStock existant = daoCommande.rechercherParId(id);
        existant.setEtatLivraison(etatLivraison);
        daoCommande.modifier(existant);
        
        // appel le webservice de maj projet1
        ServiceMajWebservice service = new ServiceMaj().getServiceMajPort();
        
        DtoMajCommande majCommande = new DtoMajCommande();
        if(etatLivraison == EtatLivraison.VALIDE){
            majCommande.setEtatLivraison(fr.afcepf.groupe1.projet1.servicemaj.EtatLivraison.VALIDE);   
        }else if(etatLivraison == EtatLivraison.ATTENTE_VALIDATION_PAIEMENT){
            majCommande.setEtatLivraison(fr.afcepf.groupe1.projet1.servicemaj.EtatLivraison.ATTENTE_VALIDATION_PAIEMENT);  
        }else if(etatLivraison == EtatLivraison.ANNULE){
            majCommande.setEtatLivraison(fr.afcepf.groupe1.projet1.servicemaj.EtatLivraison.ANNULE);
        }else if(etatLivraison == EtatLivraison.PAYE){
            majCommande.setEtatLivraison(fr.afcepf.groupe1.projet1.servicemaj.EtatLivraison.PAYE);
        }else if(etatLivraison == EtatLivraison.EN_PREPARATION){
            majCommande.setEtatLivraison(fr.afcepf.groupe1.projet1.servicemaj.EtatLivraison.EN_PREPARATION);
        }else if(etatLivraison == EtatLivraison.BLOQUE){
            majCommande.setEtatLivraison(fr.afcepf.groupe1.projet1.servicemaj.EtatLivraison.BLOQUE);
        }else if(etatLivraison == EtatLivraison.EXPEDIE){
            majCommande.setEtatLivraison(fr.afcepf.groupe1.projet1.servicemaj.EtatLivraison.EXPEDIE);
        }else if(etatLivraison == EtatLivraison.LIVRE){
            majCommande.setEtatLivraison(fr.afcepf.groupe1.projet1.servicemaj.EtatLivraison.LIVRE);
        }
         
        majCommande.setIdSite(existant.getIdSite());
        
        try {
            service.majCommande(majCommande);
        } catch (EtatLivraisonException_Exception ex) {
            Logger.getLogger(ServiceCommandeStock.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvalidArgumentException_Exception ex) {
            Logger.getLogger(ServiceCommandeStock.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NotExistException_Exception ex) {
            Logger.getLogger(ServiceCommandeStock.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean creerCommande(DtoCommande commande) throws InvalidArgumentException, NotExistException, ActivationException, StockException {
        // convertion du payload commande en dto interne commande
        DtoCommandeStock dto = new DtoCommandeStock();
        dto.setAdresseLivraison(commande.getAdresseLivraison());
        dto.setCiviliteLivraison(commande.getCiviliteLivraison());
        dto.setCodePostalLivraison(commande.getCodePostalLivraison());
        dto.setDateCreation(new Date());
        dto.setIdSite(commande.getIdSite());
        dto.setModeLivraison(commande.getModeLivraison());
        dto.setNomLivraison(commande.getNomLivraison());
        dto.setPrenomLivraison(commande.getPrenomLivraison());
        dto.setTelFixeLivraison(commande.getTelFixeLivraison());
        dto.setTelMobileLivraison(commande.getTelMobileLivraison());
        dto.setVilleLivraison(commande.getVilleLivraison());
        dto.setEtatLivraison(EtatLivraison.EN_PREPARATION);
        
        // exploration des produits de la commande
        List<DtoLigneCommande> listeProduit = commande.getLignes();
        List<DtoLigneCommandeStock> lignesCommande = new ArrayList<DtoLigneCommandeStock>();
        String codeEAN13;
        Integer quantite;
        DtoProduitStock produitStock;
        DtoLigneCommandeStock ligneCourante;
        for (DtoLigneCommande produit : listeProduit) {
            codeEAN13 = produit.getCodeEAN13();
            quantite = produit.getQuantite();
            
            if(!codeEAN13.matches("^[0-9]{13}$") || quantite<1) {
                throw new InvalidArgumentException("Le produit est incorrect (ean13:"+codeEAN13+"/quantite:"+quantite);
            }
            
            produitStock = daoProduit.rechercherParCodeEAN13(codeEAN13);
            if(produitStock == null) {
                throw new NotExistException("Il n'existe pas de produit de code EAN13 = "+codeEAN13);
            }
            if(produitStock.getActif() == false) {
                throw new ActivationException("Produit désactivé ! EAN13 = "+codeEAN13);
            }
            if(produitStock.getStock() < quantite) {
                throw new StockException("Stock insuffisant sur le produit de code EAN13 = "+codeEAN13);
            }
            // Mise à jour du stock
            produitStock.setStock(produitStock.getStock() - quantite);
            daoProduit.modifier(produitStock);
            
            ligneCourante = new DtoLigneCommandeStock();
            ligneCourante.setQuantite(quantite);
            ligneCourante.setProduit(produitStock);
            lignesCommande.add(ligneCourante);
        }
        dto.setLignes(lignesCommande);
        // envoi au dao
        daoCommande.ajouter(dto);
        
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean annulerCommande(Integer idSite) throws InvalidArgumentException, NotExistException, EtatLivraisonException {
        if(idSite <= 0) {
            throw new InvalidArgumentException("Identifiant de commande incorrect : un autoincrement est sensé être positif !");
        }

        DtoCommandeStock existant = daoCommande.rechercherParIdSite(idSite);
        if(existant == null) {
            throw new NotExistException("La commande idSite = "+idSite+" n'existe pas");
        }
        if(existant.getEtatLivraison() == EtatLivraison.BLOQUE || existant.getEtatLivraison() == EtatLivraison.EXPEDIE
                || existant.getEtatLivraison() == EtatLivraison.LIVRE) {
            throw new EtatLivraisonException("Impossible d'annuler la commande, car en état "+existant.getEtatLivraison().toString());
        }
        
        daoCommande.annulerCommande(existant.getId());
        
        return true;
    }
}
